﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace WingIt
{
    [RevisionControlId("$Id: RevisionControl.cs 686 2012-08-12 16:12:20Z Chinajade $")]
    public class RevisionControl
    {
        /// <summary>
        /// Scans all the files containing [RevisionControlId("$Id: RevisionControl.cs 686 2012-08-12 16:12:20Z Chinajade $")] properties,
        /// and returns the largest value of the Revision attribute discovered.
        /// </summary>
        /// <returns></returns>
        /// 7Aug2012-06:18UTC chinajade
        // We have to do this due to Subversion design.  There is no way to acquire a 'global version number' other than at 'package time'.
        // Due to Buddywing architecture, 'package time' for a Routine is when it is compiled at runtime.  Alas, Buddywing knows nothing
        // about Subversion, so we have to figure it out ourselves.
        public static int GetRevision()
        {
            if (OverallRevision > 0)
                { return OverallRevision; }

            Assembly assembly = Assembly.GetExecutingAssembly();

            foreach (var type in assembly.GetTypes())
            {
                foreach (var attributeAsObject in type.GetCustomAttributes(false))
                {
                    RevisionControlIdAttribute attribute = attributeAsObject as RevisionControlIdAttribute;
                    if (attribute != null)
                        { OverallRevision = Math.Max(OverallRevision, attribute.Revision); }
                }
            }

            return OverallRevision;
        }

        private static int OverallRevision = -1;
    }

    /// <summary>
    /// Each file in the packages should contain a [RevisionControlId("$Id")] property.
    /// The property can be anywhere in the file, but by convention, we place it above the first class defined in the file.
    /// Subversion will take care of expanding the $Id attribute for us each time the file is checked in from a changeset modification.
    /// </summary>
    /// 7Aug2012-06:21UTC chinajade
    [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
    internal sealed class RevisionControlIdAttribute : Attribute
    {
        public RevisionControlIdAttribute(string identifier)
        {
            Id = identifier;

            foreach (Match match in Regex.Matches(identifier, IdParserPattern))
            {
                Author = match.Groups["Author"].Value.Trim();
                Date = match.Groups["Date"].Value.Trim();
                FileName = match.Groups["FileName"].Value.Trim();
                Time = match.Groups["Time"].Value.Trim();
                Revision = Convert.ToInt32(match.Groups["Revision"].Value);
            }
        }

        public string Author { get; private set; }
        public string Date { get; private set; }
        public string FileName { get; private set; }
        public string Id { get; private set; }
        public int Revision { get; private set; }
        public string Time { get; private set; }

        private static string IdParserPattern = @"^\s*\$Id:\s+(?<FileName>\S+)\s(?<Revision>\d+)\s(?<Date>\S+)\s+(?<Time>\S+)\s+(?<Author>\S+)\s*\$\s*$";
    }
}
